<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      #box {
        position: absolute;
        top: 20px;
        left: 100px;
        width: 100px;
        height: 100px;
        background-color: antiquewhite;
      }
    </style>
  </head>
  <body>
    <div id="box"></div>
    <script>
      //原理，在指定时间内从原始位置到结束位置的过程
      var box = document.getElementById('box');
      function move(ele, cssObj, duration) {
        var time = 20;
        var moveContent = duration / time; //总共需要移动多少次
        var oldStyle = {}; //原始样式
        var clock;

        for (var k in cssObj) {
          oldStyle[k] = parseInt(window.getComputedStyle(ele, null)[k]);
          // console.log( oldStyle)
        }
        var step = 0;
        clock = setInterval(function () {
          step++;
          for (var k in cssObj) {
            var moveStep = (parseInt(cssObj[k]) - oldStyle[k]) / moveContent;
            ele.style[k] = step * moveStep + oldStyle[k] + 'px';
          }
          if ((step >= moveContent)) {
            clearInterval(clock);
            for(var k in cssObj){
                ele.style[k] =  cssObj[k]
            }
          }
        }, time);
      }

      function animate(ele, targetCssObj, duration, callback) {
        var interval = 20; // 每20ms移动一次
        var moveTotalCount = duration / interval; // 移动的总次数
        var timer;
        // 得到元素ele最初始化的位置信息
        var initCssStyle = {};
        for (var cssKey in targetCssObj) {
          initCssStyle[cssKey] = parseInt(
            window.getComputedStyle(ele, null)[cssKey]
          );
        }
        // 定时器，每隔20ms移动指定的像素位置
        var count = 0;
        timer = setInterval(function () {
          count++;
          // 计算出每次移动的距离：（终点位置-起点（初始）位置） / 总移动的次数
          for (var cssKey in targetCssObj) {
            var stepMove =
              (parseInt(targetCssObj[cssKey]) - initCssStyle[cssKey]) /
              moveTotalCount;
            // 开始移动起来
            ele.style[cssKey] = initCssStyle[cssKey] + stepMove * count + 'px';
          }

          // 到达了总次数，则停止移动
          if (count >= moveTotalCount) {
            clearInterval(timer);
            // 强制拉回到终点位置，避免小数的误差
            console.log();
            for (var cssKey in targetCssObj) {
              ele.style[cssKey] = targetCssObj[cssKey] + 'px';
            }
            // 若用户传递回调则执行，没传就不执行
            callback && callback();
          }
        }, interval);
      }

      box.onclick = function () {
        // animate(box,{left :300}, 2000)
        move(box, { left: 300 }, 2000);
      };
    </script>
  </body>
</html>
